//
//  GenerationViewController.swift
//  Automobile
//
//  Created by erkebulan elzhan on 8/7/20.
//  Copyright © 2020 erkebulan elzhan. All rights reserved.
//

import UIKit
import SnapKit

// [Car Selection Mode] - comments related to this mode

final class GenerationViewController: UIViewController, Alertable {

    // MARK: - Outlets
    
    lazy private var modelsScroll: ModelsScroll = {
        let modelsScroll = ModelsScroll(models: self.models)
        return modelsScroll
    }()
    
    lazy private var tableView:UITableView = {
        let table = UITableView()
        table.delegate = self
        table.dataSource = self
        table.register(ModelCell.self, forCellReuseIdentifier: "modelCell")
        table.showsVerticalScrollIndicator = false
        table.backgroundColor = .white
        table.tableFooterView = UIView()
        table.separatorStyle = .none
        return table
    }()
    
    lazy private var spinner = SpinnerView()
    
    lazy private var nextBtn: UIButton = {
        let btn = UIButton()
        btn.clipsToBounds = true
        btn.layer.cornerRadius = 15
        btn.setTitle("Далее", for: .normal)
        btn.backgroundColor = .lightBlueColor
        btn.setTitleColor(.greyColor, for: .normal)
        btn.titleLabel!.font = UIFont.systemFont(ofSize: 17, weight: .medium)
        return btn
    }()
    
    lazy private var submitBtn: UIButton = {
        let btn = UIButton()
        btn.clipsToBounds = true
        btn.layer.cornerRadius = 15
        btn.setTitle("Готово", for: .normal)
        btn.backgroundColor = .blueColor
        btn.setTitleColor(.white, for: .normal)
        btn.titleLabel!.font = UIFont.systemFont(ofSize: 17, weight: .medium)
        return btn
    }()
    
    lazy private var emptyView: EmptyView = {
        let emptyView = EmptyView()
        emptyView.frame = CGRect(x: 0, y: 0, width: tableView.frame.width, height: 200)
        return emptyView
    }()
    
    // MARK: - Props
    
    public var resultsVC: ResultsVCDelegate!
    public var carData: CarData!
    public var models: [Model]! {
        didSet {
            tableView.reloadData()
            self.handleEmpty()
        }
    }
    private var generationModels: [Int: [GenerationModel]] = [:]
    private var currentModelIndex: Int = 0
    private var lastModelRow: Int?
    
    private var isLoading: Bool = false {
        didSet {
            isLoading ? spinner.startAnimating() : spinner.stopAnimating()
        }
    }
    
    private var selectedItemsCount: Int = 0 {
        didSet {
            if (!isCarCreate) {
                if (selectedItemsCount == 0 && !nextBtn.isHidden) {
                    self.nextBtn.isHidden = true
                    tableBottomCons?.update(inset: 0)
                } else if nextBtn.isHidden {
                    self.nextBtn.isHidden = false
                    tableBottomCons?.update(inset: -56)
                }
            }
        }
    }
    
    private var isCarCreate: Bool {
        return resultsVC is SelectCarViewController
    }
    
    private var tableBottomCons: Constraint?
    
    // MARK: - Actions
    
    @objc private func updateModel (notification: NSNotification) {
        
        guard let userInfo = notification.userInfo else {
            return
        }
        
        if let model = userInfo["model"] as? Model, let index = userInfo["index"] as? Int {
            if (index != self.currentModelIndex) {
                if isCarCreate && lastModelRow != nil {
                    generationModels[currentModelIndex]?[lastModelRow!].isSelected = false
                    lastModelRow = nil
                }
                self.currentModelIndex = index
                if (models[index].generation == nil) {
                    self.loadGeneration(model: model, index: index)
                } else {
                    tableView.reloadData()
                    handleEmpty()
                }
            }
        }
    }
    
    // Return to Root
    @objc private func goBack (sender: UIBarButtonItem) {
        self.navigationController?.popViewController(animated: true)
    }
    
    @objc private func closeVC (sender: UIBarButtonItem) {
        self.navigationController?.dismiss(animated: true, completion: nil)
    }
    
    
    // Select Serie (Only Multi)
    
    @objc private func onNext (sender: UIButton) {
        let vc = SerieModificationViewController()
        vc.vcType = .serie
        carData.models = self.getModels()
        vc.carData = carData
        vc.models = self.getModels()
        vc.resultsVC = self.resultsVC
        self.navigationController?.pushViewController(vc, animated: true)
    }
    
    @objc private func onSubmit (sender: UIButton) {
        resultsVC.goBack(data: CarFilter(marka: carData.marka, models: self.models), type: .exclude)
        
        if isCarCreate {
            navigationController?.dismiss(animated: true, completion: nil)
        } else {
            navigationController?.popViewController(animated: true)
        }
    }
    
    // MARK: - Init
    
    override func viewDidLoad() {
        super.viewDidLoad()
        selectedItemsCount = 0
        self.setUpUI()
        self.setUpNavBar()
        NotificationCenter.default.addObserver(self, selector: #selector(updateModel(notification:)), name: NSNotification.Name("setModel"), object: nil)
        if isCarCreate {
            self.handleSingleSelection()
        }
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.loadGeneration(model: models[currentModelIndex], index: currentModelIndex)
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name("setModel"), object: nil)
    }
    
    // MARK: - Methods
    
    private func getTitle () -> String {
        let generations = models.map {
            $0.name_ru
        }.joined(separator: ", ")
        return "Поколении " + (carData.marka?.name_ru ?? "") + " " + generations
    }
    
    private func handleEmpty () {
        if ((models[currentModelIndex].generation ?? []).count == 0) {
            tableView.tableHeaderView = emptyView
        } else {
            tableView.tableHeaderView = nil
        }
    }

    private func fillGenerationModel () {
        var _models: [GenerationModel] = []
        for model in models[currentModelIndex].generation ?? [] {
            let gModel = GenerationModel(generation: model)
            _models.append(gModel)
        }
        generationModels[currentModelIndex] = _models
    }
    
    private func getModels () -> [Model] {
        var _models = models
        for (i, _) in self.models.enumerated() {
            var _generations:[Generation] = []
            if let generationModel = generationModels[i] {
                for gModel in generationModel {
                    if gModel.isSelected {
                        _generations.append(gModel.generation)
                    }
                }
            }
            _models![i].generation = _generations
        }
        return _models!
    }
}

// MARK: - Network

extension GenerationViewController {
    
    private func loadGeneration (model: Model, index: Int) {
        let backendService = Backend()
        let parameters:[URLQueryItem] = [
            URLQueryItem(name: "model_id", value: "\(model.id)")
        ]
        let _request = Request(base: carData.saveToGarage ? .garage : .advert, parameters: parameters)
        let requestUrl = _request.getUrl(path: "cars/generations")
        let request = URLRequest(url: requestUrl)
        self.isLoading = true
        
        backendService.fetchFromBackend(for: Response<[Generation]>.self, request: request, statusCode: 200) { (result) in
            self.isLoading = false
            switch result {
                case .failure(let error):
                    switch error {
                    case .general:
                        self.showAlert("Упс...", "Неизвестная ошибка")
                    case .parameter(let msg):
                        self.showAlert("Упс...", msg)
                }
                case .success(let _data):
                    self.models[index].generation = _data.results
                    self.fillGenerationModel()
            }
        }
    }
}

// MARK: - UI Table View

extension GenerationViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if isCarCreate {
            let vc = SerieModificationViewController()
            vc.vcType = .serie
            var singleModel = models[0]
            singleModel.generation = [generationModels[currentModelIndex]![indexPath.row].generation]
            carData.models = [singleModel]
            vc.carData = carData
            vc.models = [singleModel]
            vc.resultsVC = self.resultsVC
            self.navigationController?.pushViewController(vc, animated: true)
        } else {
            self.updateCheckboxes(at: indexPath)
        }
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return (models[currentModelIndex].generation ?? []).count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "modelCell") as! ModelCell
        cell.model = generationModels[currentModelIndex]?[indexPath.row]
        cell.selectionStyle = .none
        cell.backgroundColor = .white
        
        // [Car Selection Mode]
        if isCarCreate {
            cell.handleSingleSelection(markIcon: carData.markaImg)
        }
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 200
    }
    
    private func updateCheckboxes (at indexPath: IndexPath) {
        if generationModels[currentModelIndex]?[indexPath.row].isSelected ?? false {
            selectedItemsCount -= 1
        } else {
            selectedItemsCount += 1
        }
        generationModels[currentModelIndex]?[indexPath.row].isSelected.toggle()
        if isCarCreate && lastModelRow != nil {
            generationModels[currentModelIndex]?[lastModelRow!].isSelected = false
            selectedItemsCount -= 1
            tableView.reloadRows(at: [IndexPath(row: lastModelRow!, section: 0)], with: .top)
        }
        lastModelRow = indexPath.row
        tableView.reloadRows(at: [indexPath], with: .top)
    }
}

// MARK: - UI

extension GenerationViewController {
    
    private func setUpUI () {
        view.backgroundColor = .white
        self.view.addSubview(tableView)
        self.view.addSubview(spinner)
        
        // [Car Selection Mode]
        if !isCarCreate {
            self.view.addSubview(modelsScroll)
            self.view.addSubview(nextBtn)
            self.view.addSubview(submitBtn)
            nextBtn.addTarget(self, action: #selector(onNext(sender:)), for: .touchUpInside)
            submitBtn.addTarget(self, action: #selector(onSubmit(sender:)), for: .touchUpInside)
        }
        
        self.addConstraints()
    }
    
    private func addConstraints () {
        let viewsTop = !isCarCreate ? modelsScroll.snp.bottom : view.safeAreaLayoutGuide.snp.top
        let tableBottom = !isCarCreate ? submitBtn.snp.top : view.safeAreaLayoutGuide.snp.bottom
        
        // [Car Selection Mode]
        
        if !isCarCreate {
            modelsScroll.snp.makeConstraints { (make) in
                make.top.equalTo(view.safeAreaLayoutGuide).offset(20)
                make.leading.trailing.equalToSuperview().inset(16)
                make.height.equalTo(48.0)
            }
            submitBtn.snp.makeConstraints { (make) in
                make.bottom.equalTo(view.safeAreaLayoutGuide).inset(20)
                make.leading.trailing.equalToSuperview().inset(16)
                make.height.equalTo(44)
            }
            nextBtn.snp.makeConstraints { (make) in
                make.bottom.equalTo(submitBtn.snp.top).inset(-8)
                make.leading.trailing.equalToSuperview().inset(16)
                make.height.equalTo(44)
            }
        }
        
        tableView.snp.makeConstraints { (make) in
            make.top.equalTo(viewsTop).offset(40)
            make.leading.trailing.equalToSuperview().inset(16)
            tableBottomCons = make.bottom.equalTo(tableBottom).offset(-12).constraint
        }
        spinner.snp.makeConstraints { (make) in
            make.center.equalToSuperview()
        }
    }
    
    private func setUpNavBar () {
        let backIcon = UIImage(named: "cancel")
        let backButton = UIBarButtonItem(image: backIcon, landscapeImagePhone: backIcon, style: .plain, target: self, action: #selector(goBack(sender:)))
        backButton.tintColor = .greyColor
        
        self.navigationItem.simpleNavBar(title: "Поколение", backButton: backButton)
        navigationItem.largeTitleDisplayMode = .always
        navigationController?.navigationBar.largeTitleTextAttributes = [
            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 24, weight: .bold)
        ]
        navigationItem.title = self.getTitle()
        navigationItem.hidesSearchBarWhenScrolling = false
        self.navigationController?.navigationBar.defaultNavBar()
        self.navigationController?.navigationItem.largeTitleDisplayMode = .always
    }
    
    // MARK: - [Car Selection Mode]
    
    
    private func handleSingleSelection () {
        self.tableView.separatorStyle = .singleLine
        self.addCloseIcon()
    }
    
    private func addCloseIcon () {
        let closeBarBnt = UIBarButtonItem(image: UIImage(named: "dismiss"), style: .plain, target: self, action: #selector(closeVC))
        closeBarBnt.tintColor = .greyColor
        self.navigationItem.rightBarButtonItem = closeBarBnt
    }
}


